﻿namespace Algo.Sort
{
    using System.Collections.Generic;

    internal sealed class GnomeSortStrategy : ISortStrategy
    {
        public IEnumerable<T> Sort<T>(IEnumerable<T> items, IComparer<T> comparer, IAlgoExtensions extensions)
        {
            var iterationsCount = 0;
            var list = SortUtilities.CopyToList(items);
            if (list.Count <= 1)
            {
                return list;
            }

            try
            {
                var position = 0;
                var lastSortedPosition = 0;
                var size = list.Count - 1;
                while (position < size)
                {
                    var nextPosition = position + 1;
                    if (SortUtilities.IsGreaterThen(comparer, list[position], list[nextPosition]))
                    {
                        SortUtilities.Swap(list, position, nextPosition);
                        position--;

                        if (position < 0)
                        {
                            position = lastSortedPosition + 1;
                        }
                    }
                    else
                    {
                        lastSortedPosition++;
                        position = lastSortedPosition;
                    }

                    iterationsCount++;
                }
            }
            finally
            {
                IMetricsExtension metricsBehaviour;
                if (extensions.TryGet(out metricsBehaviour))
                {
                    metricsBehaviour.RegisterIterations(iterationsCount);
                }
            }

            return list;
        }
    }
}
